#pragma once
#include "List.h"
#include "helper.h"
template <typename T>
class Event
{
private:
	List<T> _events;

public:
	Event()
	{
		_events = List<T>();
	}
	~Event()
	{
		_events.resize(0);
	}
	template <class... Args>
	void Invoke(Args... args)
	{
		for (int i = 0; i < _events.Count; i++)
		{
			_events[i](args...);
		}
	}
	void operator+=(T v)
	{
		_events.Add(v);
	}
	void operator-=(T v)
	{
		_events.Remove(v);
	}
	template <class... Args>
	void operator()(Args... args)
	{
		for (int i = 0; i < _events.Count; i++)
		{
			_events[i](args...);
		}
	}
	int Count()
	{
		return _events.Count;
	}
	void Clear()
	{
		_events.Clear();
	}
};
class EventArgs
{
public:
	EventArgs() {}
};
enum MouseButtons
{
	MouseButtons_None = 0x00000000,
	MouseButtons_Left = 0x00100000,
	MouseButtons_Right = 0x00200000,
	MouseButtons_Middle = 0x00400000,
	MouseButtons_XButton1 = 0x00800000,
	MouseButtons_XButton2 = 0x01000000
};
static MouseButtons FromParamToMouseButtons(UINT message)
{

	switch (message)
	{
	case WM_MOUSEWHEEL:
		return MouseButtons_Middle; // Mouse wheel scrolling
	case WM_LBUTTONDOWN:
		return MouseButtons_Left; // Left click press
	case WM_RBUTTONDOWN:
		return MouseButtons_Right; // Right click to press
	case WM_MBUTTONDOWN:
		return MouseButtons_Middle; // Press the middle button
	case WM_LBUTTONUP:
		return MouseButtons_Left; // Left click release
	case WM_RBUTTONUP:
		return MouseButtons_Right; // Right click release
	case WM_MBUTTONUP:
		return MouseButtons_Middle; // Middle key released
	case WM_LBUTTONDBLCLK:
		return MouseButtons_Left; // Double click the mouse
	}
	return MouseButtons_None;
}
enum Keys
{
	Keys_None = 0x00000000,
	Keys_LButton = 0x00000001,
	Keys_RButton = 0x00000002,
	Keys_Cancel = 0x00000003,
	Keys_MButton = 0x00000004,
	Keys_XButton1 = 0x00000005,
	Keys_XButton2 = 0x00000006,
	Keys_Back = 0x00000008,
	Keys_Tab = 0x00000009,
	Keys_LineFeed = 0x0000000A,
	Keys_Clear = 0x0000000C,
	Keys_Return = 0x0000000D,
	Keys_Enter = 0x0000000D,
	Keys_ShiftKey = 0x00000010,
	Keys_ControlKey = 0x00000011,
	Keys_Menu = 0x00000012,
	Keys_Pause = 0x00000013,
	Keys_CapsLock = 0x00000014,
	Keys_Capital = 0x00000014,
	Keys_KanaMode = 0x00000015,
	Keys_HanguelMode = 0x00000015,
	Keys_HangulMode = 0x00000015,
	Keys_JunjaMode = 0x00000017,
	Keys_FinalMode = 0x00000018,
	Keys_KanjiMode = 0x00000019,
	Keys_HanjaMode = 0x00000019,
	Keys_Escape = 0x0000001B,
	Keys_IMEConvert = 0x0000001C,
	Keys_IMENonconvert = 0x0000001D,
	Keys_IMEAceept = 0x0000001E,
	Keys_IMEModeChange = 0x0000001F,
	Keys_Space = 0x00000020,
	Keys_PageUp = 0x00000021,
	Keys_Prior = 0x00000021,
	Keys_PageDown = 0x00000022,
	Keys_Next = 0x00000022,
	Keys_End = 0x00000023,
	Keys_Home = 0x00000024,
	Keys_Left = 0x00000025,
	Keys_Up = 0x00000026,
	Keys_Right = 0x00000027,
	Keys_Down = 0x00000028,
	Keys_Select = 0x00000029,
	Keys_Print = 0x0000002A,
	Keys_Execute = 0x0000002B,
	Keys_PrintScreen = 0x0000002C,
	Keys_Snapshot = 0x0000002C,
	Keys_Insert = 0x0000002D,
	Keys_Delete = 0x0000002E,
	Keys_Help = 0x0000002F,
	Keys_D0 = 0x00000030,
	Keys_D1 = 0x00000031,
	Keys_D2 = 0x00000032,
	Keys_D3 = 0x00000033,
	Keys_D4 = 0x00000034,
	Keys_D5 = 0x00000035,
	Keys_D6 = 0x00000036,
	Keys_D7 = 0x00000037,
	Keys_D8 = 0x00000038,
	Keys_D9 = 0x00000039,
	Keys_A = 0x00000041,
	Keys_B = 0x00000042,
	Keys_C = 0x00000043,
	Keys_D = 0x00000044,
	Keys_E = 0x00000045,
	Keys_F = 0x00000046,
	Keys_G = 0x00000047,
	Keys_H = 0x00000048,
	Keys_I = 0x00000049,
	Keys_J = 0x0000004A,
	Keys_K = 0x0000004B,
	Keys_L = 0x0000004C,
	Keys_M = 0x0000004D,
	Keys_N = 0x0000004E,
	Keys_O = 0x0000004F,
	Keys_P = 0x00000050,
	Keys_Q = 0x00000051,
	Keys_R = 0x00000052,
	Keys_S = 0x00000053,
	Keys_T = 0x00000054,
	Keys_U = 0x00000055,
	Keys_V = 0x00000056,
	Keys_W = 0x00000057,
	Keys_X = 0x00000058,
	Keys_Y = 0x00000059,
	Keys_Z = 0x0000005A,
	Keys_LWin = 0x0000005B,
	Keys_RWin = 0x0000005C,
	Keys_Apps = 0x0000005D,
	Keys_NumPad0 = 0x00000060,
	Keys_NumPad1 = 0x00000061,
	Keys_NumPad2 = 0x00000062,
	Keys_NumPad3 = 0x00000063,
	Keys_NumPad4 = 0x00000064,
	Keys_NumPad5 = 0x00000065,
	Keys_NumPad6 = 0x00000066,
	Keys_NumPad7 = 0x00000067,
	Keys_NumPad8 = 0x00000068,
	Keys_NumPad9 = 0x00000069,
	Keys_Multiply = 0x0000006A,
	Keys_Add = 0x0000006B,
	Keys_Separator = 0x0000006C,
	Keys_Subtract = 0x0000006D,
	Keys_Decimal = 0x0000006E,
	Keys_Divide = 0x0000006F,
	Keys_F1 = 0x00000070,
	Keys_F2 = 0x00000071,
	Keys_F3 = 0x00000072,
	Keys_F4 = 0x00000073,
	Keys_F5 = 0x00000074,
	Keys_F6 = 0x00000075,
	Keys_F7 = 0x00000076,
	Keys_F8 = 0x00000077,
	Keys_F9 = 0x00000078,
	Keys_F10 = 0x00000079,
	Keys_F11 = 0x0000007A,
	Keys_F12 = 0x0000007B,
	Keys_F13 = 0x0000007C,
	Keys_F14 = 0x0000007D,
	Keys_F15 = 0x0000007E,
	Keys_F16 = 0x0000007F,
	Keys_F17 = 0x00000080,
	Keys_F18 = 0x00000081,
	Keys_F19 = 0x00000082,
	Keys_F20 = 0x00000083,
	Keys_F21 = 0x00000084,
	Keys_F22 = 0x00000085,
	Keys_F23 = 0x00000086,
	Keys_F24 = 0x00000087,
	Keys_NumLock = 0x00000090,
	Keys_Scroll = 0x00000091,
	Keys_LShiftKey = 0x000000A0,
	Keys_RShiftKey = 0x000000A1,
	Keys_LControlKey = 0x000000A2,
	Keys_RControlKey = 0x000000A3,
	Keys_LMenu = 0x000000A4,
	Keys_RMenu = 0x000000A5,
	Keys_BrowserBack = 0x000000A6,
	Keys_BrowserForward = 0x000000A7,
	Keys_BrowserRefresh = 0x000000A8,
	Keys_BrowserStop = 0x000000A9,
	Keys_BrowserSearch = 0x000000AA,
	Keys_BrowserFavorites = 0x000000AB,
	Keys_BrowserHome = 0x000000AC,
	Keys_VolumeMute = 0x000000AD,
	Keys_VolumeDown = 0x000000AE,
	Keys_VolumeUp = 0x000000AF,
	Keys_MediaNextTrack = 0x000000B0,
	Keys_MediaPreviousTrack = 0x000000B1,
	Keys_MediaStop = 0x000000B2,
	Keys_MediaPlayPause = 0x000000B3,
	Keys_LaunchMail = 0x000000B4,
	Keys_SelectMedia = 0x000000B5,
	Keys_LaunchApplication1 = 0x000000B6,
	Keys_LaunchApplication2 = 0x000000B7,
	Keys_OemSemicolon = 0x000000BA,
	Keys_Oemplus = 0x000000BB,
	Keys_Oemcomma = 0x000000BC,
	Keys_OemMinus = 0x000000BD,
	Keys_OemPeriod = 0x000000BE,
	Keys_OemQuestion = 0x000000BF,
	Keys_Oemtilde = 0x000000C0,
	Keys_OemOpenBrackets = 0x000000DB,
	Keys_OemPipe = 0x000000DC,
	Keys_OemCloseBrackets = 0x000000DD,
	Keys_OemQuotes = 0x000000DE,
	Keys_Oem8 = 0x000000DF,
	Keys_OemBackslash = 0x000000E2,
	Keys_ProcessKey = 0x000000E5,
	Keys_Attn = 0x000000F6,
	Keys_Crsel = 0x000000F7,
	Keys_Exsel = 0x000000F8,
	Keys_EraseEof = 0x000000F9,
	Keys_Play = 0x000000FA,
	Keys_Zoom = 0x000000FB,
	Keys_NoName = 0x000000FC,
	Keys_Pa1 = 0x000000FD,
	Keys_OemClear = 0x000000FE,
	Keys_KeyCode = 0x0000FFFF,
	Keys_Shift = 0x00010000,
	Keys_Control = 0x00020000,
	Keys_Alt = 0x00040000,
	Keys_Modifiers = ((int)0xFFFF0000),
	Keys_IMEAccept = 0x0000001E,
	Keys_Oem1 = 0x000000BA,
	Keys_Oem102 = 0x000000E2,
	Keys_Oem2 = 0x000000BF,
	Keys_Oem3 = 0x000000C0,
	Keys_Oem4 = 0x000000DB,
	Keys_Oem5 = 0x000000DC,
	Keys_Oem6 = 0x000000DD,
	Keys_Oem7 = 0x000000DE,
	Keys_Packet = 0x000000E7,
	Keys_Sleep = 0x0000005F
};
class MouseEventArgs : EventArgs
{
public:
	MouseButtons Buttons;
	int Clicks;
	int Delta;
	int X;
	int Y;
	MouseEventArgs() {}
	MouseEventArgs(MouseButtons button, int clicks, int x, int y, int delta)
	{
		this->Buttons = button;
		this->Clicks = clicks;
		this->Delta = delta;
		this->X = x;
		this->Y = y;
	}
};
class KeyEventArgs : EventArgs
{
public:
	Keys KeyData;
	bool EventHandled;
	bool SupressKeyPress;
	KeyEventArgs() {}
	KeyEventArgs(Keys keyData)
	{
		this->KeyData = keyData;
		this->EventHandled = false;
	}
	bool Alt()
	{
		return ((this->KeyData & Keys::Keys_Alt) != 0);
	}
	bool Control()
	{
		return ((this->KeyData & Keys::Keys_Control) != 0);
	}
	bool Shift()
	{
		return ((this->KeyData & Keys::Keys_Shift) != 0);
	}
	Keys Modifiers()
	{
		return (Keys)(this->KeyData & Keys::Keys_Modifiers);
	}
	Keys KeyCode()
	{
		return (Keys)(this->KeyData & Keys::Keys_KeyCode);
	}
	int KeyValue()
	{
		return (int)this->KeyData;
	}
	static KeyEventArgs ProcessKeyEventArgs(MSG m)
	{
		return KeyEventArgs((Keys)(m.wParam | 0));
	}
};
typedef Event<void (*)(class Control *, EventArgs)> EventHandler;
typedef Event<void (*)(class Control *)> OnCheckedEvent;
typedef Event<void (*)(class Control *, MouseEventArgs)> MouseWheelEvent;
typedef Event<void (*)(class Control *, MouseEventArgs)> MouseMoveEvent;
typedef Event<void (*)(class Control *, MouseEventArgs)> MouseUpEvent;
typedef Event<void (*)(class Control *, MouseEventArgs)> MouseDownEvent;
typedef Event<void (*)(class Control *, MouseEventArgs)> MouseDoubleEvent;
typedef Event<void (*)(class Control *, MouseEventArgs)> MouseClickEvent;
typedef Event<void (*)(class Control *, MouseEventArgs)> MouseEnterEvent;
typedef Event<void (*)(class Control *, MouseEventArgs)> MouseLeavedEvent;
typedef Event<void (*)(class Control *, KeyEventArgs)> KeyUpEvent;
typedef Event<void (*)(class Control *, KeyEventArgs)> KeyDownEvent;
typedef Event<void (*)(class Control *)> OnPaintEvent;
typedef Event<void (*)(class Control *, int c, int r, bool v)> OnGridViewCheckStateChangedEvent;
typedef Event<void (*)(class Control *)> OnCloseEvent;
typedef Event<void (*)(class Control *)> MovedEvent;
typedef Event<void (*)(class Control *)> SizeChangedEvent;
typedef Event<void (*)(class Control *)> ScrollChangedEvent;
typedef Event<void (*)(class Control *, std::wstring, std::wstring)> TextChangedEvent;
typedef Event<void (*)(class Control *, List<std::wstring>)> DropFileEvent;

typedef Event<void (*)(class Control *, wchar_t)> OnCharInputEvent;

typedef Event<void (*)(class Control *)> GotFocusEvent;
typedef Event<void (*)(class Control *)> LostFocusEvent;